/* eslint-disable */
import axios from 'axios';
// import Eos from 'eosjs';
import Eos from 'eosjs-without-sort';
import Ecc from 'eosjs-ecc';
import Fcbuffer from 'fcbuffer';
import Enu from 'enujs';
import Fibos from 'fibos.js';
import store from '@/store';
import Io from '@/utils/socket';
import scatterJS from 'scatterjs-core';
import ScatterEOS from 'scatterjs-plugin-eosjs';
import * as waxjs from '@waxio/waxjs/dist';
import { WaxModel } from '@/utils/eos/wax';
import { toFixed, accSub, getReqUrl } from '@/utils/validate';

scatterJS.plugins( new ScatterEOS() );
const abi = require("./eosio.system.json");

/*
* 安装 Scatter 与否
* get scatter
*/
let scatterConnected = false;
let scatappOnline = false;
// scatter 最大重连次数
const maxFrequency = 50;
let nowFrequency = 0;
let mobileWalletFrequency = 0;

class model {

  constructor() {
    this.vthis = null;
    this.scatter = null; // 登录、退出对象
    this.enuScatter = null; // 登录、退出对象
    this.scatterEosJs = null; // 登录后的各种操作对象
    this.accountByScatter = null;
    this.chainName = null;
    this.env = process.env.NODE_ENV;
    this.scatapp = null;
    // 配置
    this.EosJs = null;
    this.EosJsUse = null;
    this.BosJs = null;
    this.MeeJs = null;
    this.EnuJs = null;
    this.FibosJs = null;
    this.TelosJs = null;
    this.Wax = null;
    this.network = null;
    this.eosOptions = null;
    this.enuConnected = false;
    this.actor = this.env === 'production' ? '111.3' : '11111111aaaa';
  }

  scatterInit(vthis, callback) {
    const self = this;
    this.vthis = vthis;
    this.scatapp = store.state.app.scatter || {};
    this.chainName = this.scatapp.chain || 'eos';
    if (location.pathname.indexOf('embed-trade') >= 0
    || location.pathname.indexOf('embed-swap') >= 0) return;
    scatterJS.scatter.connect('newdex.io').then(async connected => {
      if (self.scatapp.wallet === 'Ironman') return;
      if (self.scatapp.wallet === 'lynxwallet') return;
      scatterConnected = connected;
      if (!connected) {
        nowFrequency += 1;
        if (nowFrequency > maxFrequency
          && this.scatapp.by !== 'mobileWallet'
          && this.scatapp.wallet !== 'cloudWallet') {
          // 退出当前账户
          this.storeAccountOut(this.scatapp);
          return;
        }
        this.scatapp.online = false;
        store.dispatch('setScatter', this.scatapp);
        sessionStorage.setItem('scatterInstall', 0);
        setTimeout(() => {
          self.scatterInit(self.vthis, callback);
        }, 500);
        return false;
      };
      console.log('Scatter connected!');
      scatappOnline = true;
      sessionStorage.setItem('scatterInstall', 1);
      if (self.scatapp.wallet === 'Ironman') return;
      // console.log('配置 --- scatterEosJs');
      self.scatter = scatterJS.scatter;
      window.scatter = null;
      window.ScatterJS = null;
      self.scatapp.online = true;
      // 获取scatter来源
      let scatterFrom = 'Scatter';
      try {
        const getVersion = await scatterJS.scatter.getVersion();
        if (getVersion && getVersion.indexOf(' ') >= 0 && getVersion.split(' ')[0]) {
          scatterFrom = getVersion.split(' ')[0].toLowerCase(); // leafwallet 叶子钱包
        }
        self.scatapp.scatterFrom = scatterFrom;
        store.dispatch('setScatter', self.scatapp);
        self.initNext();
        callback();
      } catch (error) {
        console.log(error);
        self.scatapp.scatterFrom = scatterFrom;
        store.dispatch('setScatter', self.scatapp);
        self.initNext();
        callback();
      }
    });
  }
  enuInit(vthis, callback) {
    const self = this;
    self.vthis = vthis;
    this.scatapp = store.state.app.scatter || {};
    navigator.userAgent == "EOSLynx Desktop"
    document.addEventListener('ironmanLoaded', ironmanExtension => {
      self.enuConnected = true;
      self.enuScatter = window.ironman;
      if (this.scatapp.wallet === 'Ironman') {
        self.scatter = self.enuScatter;
      }
      window.ironman = null;
      callback();
    });
  }

  lynxInit(vthis, callback) {
    const self = this;
    self.vthis = vthis;
    this.scatapp = store.state.app.scatter || {};
    console.log('Lynx Connecting...');
    document.addEventListener('lynxMobileLoaded', lynxMobileLoaded => {
      console.log('lLynx Loaded');
      callback();
    });
  }

  initNext() {
    if (location.pathname.indexOf('embed-trade') >= 0
    || location.pathname.indexOf('embed-swap') >= 0) return;
    if (this.scatter && !this.scatter.identity) {
      if (this.scatapp.wallet === 'Scatter') {
        const scatterItem = this.scatapp;
        scatterItem.identity = null;
        scatterItem.wallet = '';
        scatterItem.chain = 'eos';
        store.dispatch('setScatter', scatterItem);
        this.accountByScatter = null;
      }
      return;
    }
    if (this.scatapp && this.scatapp.identity) {
      this.accountByScatter = store.state.app.scatter.identity.accounts[0];
    }
  }

  // 节点配置 / 节点切换
  async chainNodeInit(chainVal) {
    let chain = chainVal || 'eos';
    chain = chain.toLowerCase();
    const envobj = this.returnChainInfo(chain);
    this.scatter = scatterJS.scatter;
    if (chain === 'enu' || chain === 'fibos') {
      this.scatter = this.enuScatter;
    }
    let blockchain = 'eos';
    let newObj = Eos({
      httpEndpoint: envobj.url,
      chainId: envobj.chainId,
      verbose: false,
    });
    if (chain === 'eos'
    || chain === 'bos'
    || chain === 'wax'
    || chain === 'meetone'
    || chain === 'lynx') {
      this.EosJsUse = newObj;
    }
    if (chain === 'enu') {
      blockchain = chain;
      newObj = Enu({
        keyProvider: '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3',// private key
        httpEndpoint: envobj.url,
        chainId: envobj.chainId,
        verbose: false,
      });
    }
    if (chain === 'fibos') {
      blockchain = chain;
      newObj = Fibos({
        httpEndpoint: envobj.url,
        chainId: envobj.chainId,
        verbose: false,
      });
      this.FibosJs = newObj;
    }
    if (chain === 'wax') {
      this.chainName = chain;
      this.Wax = new waxjs.WaxJS(envobj.url);
      WaxModel.init(this.vthis, this.Wax);
    }
    this.network = {
      blockchain,
      protocol: envobj.protocol,
      host: envobj.host,
      port: envobj.port,
      chainId: envobj.chainId,
    };
    this.eosOptions = {
      broadcast: true,
      sign: true,
      chainId: envobj.chainId,
    };
    // console.log(chain, this.chainName);
    if (chain === this.chainName) {
      this.EosJs = newObj;
    }
    if (this.scatter && this.scatter.identity) {
      if (this.scatapp.wallet === 'Ironman') {
        this.scatterEosJs = await this.scatter.enu(this.network, Enu, this.eosOptions);
        if (this.chainName === 'fibos') {
          this.scatterEosJs = await this.scatter.enu(this.network, Fibos, this.eosOptions);
        }
      } else {
        this.scatterEosJs = await this.scatter.eos(this.network, Eos, this.eosOptions);
      }
    }
    // 如果是扫码登录的用户
    this.scatapp = store.state.app.scatter;
    const frontendToken = localStorage.getItem('Frontend-Token');
    if (this.scatapp && this.scatapp.by === 'mobileWallet' && mobileWalletFrequency >= 3 && !frontendToken) {
      this.vthis.$message.error(this.vthis.$t('public.walletDesktop'));
    }
    if (mobileWalletFrequency <= 4) {
      mobileWalletFrequency += 1
    }
  }

  // 节点信息获取
  returnChainInfo(cname) {
    const chainName = cname.toLowerCase();
    let envobj = store.state.app.nodeChecked[chainName];
    if (!envobj){
      return {
        area: 'Hongkong, HK',
        chainId: "aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906",
        host: 'eos.newdex.one',
        port: '443',
        protocol: 'https',
        url: 'https://eos.newdex.one'
      };
    }
    // if (chainName === 'eos') {
    //   switch (this.env) {
    //     case 'test':
    //     case 'test2':
    //     case 'development':
    //       // envobj.chainId = 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f';
    //       envobj.chainId = '5fff1dae8dc8e2fc4d5b23b2c7665c97f9e9d8edf2b6485a86ba311c25639191';
    //       break;
    //     case 'production':
    //       envobj.chainId = 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906';
    //       break;
    //     default:
    //       break;
    //   }
    // }
    // if (chainName === 'bos') {
    //   // envobj = { // bos 正式链
    //   //   host: "api.bossweden.org",
    //   //   url: "https://api.bossweden.org",
    //   //   port: "443",
    //   //   protocol: "https",
    //   // };
    //   switch (this.env) {
    //     case 'test':
    //     case 'test2':
    //     case 'development':
    //       envobj.chainId = 'ab8a0e2ba14a316784fc71348b1f99e61628138f1af4f18cd859fd4af43ce5cc';
    //       // envobj.chainId = 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f';
    //       break;
    //     case 'production':
    //       envobj.chainId = 'd5a3d18fbb3c084e3b1f3fa98c21014b5f3db536cc15d08f9f6479517c6a3d86';
    //       break;
    //     default:
    //       break;
    //   }
    // }
    // if (chainName === 'meetone') {
    //   // envobj = { // meetone 正式链
    //   //   host: "api.bossweden.org",
    //   //   url: "https://api.bossweden.org",
    //   //   port: "443",
    //   //   protocol: "https",
    //   // };
    //   // https://api.bossweden.org/v1/chain/get_info
    //   switch (this.env) {
    //     case 'test':
    //     case 'test2':
    //     case 'development':
    //       // envobj.chainId = 'c166dbf9854b8a07e87bb6faf87e25768c14bcb06ee7e3131bcc027106606bad';
    //       envobj.chainId = '5fff1dae8dc8e2fc4d5b23b2c7665c97f9e9d8edf2b6485a86ba311c25639191';
    //       break;
    //     case 'production':
    //       envobj.chainId = 'cfe6486a83bad4962f232d48003b1824ab5665c36778141034d75e57b956e422';
    //       break;
    //     default:
    //       break;
    //   }
    // }
    // if (chainName === 'enu') {
    //   // https://enu.qsx.io/v1/chain/get_info
    //   // envobj = { // meetone 正式链
    //   //   host: "rpc.enu.one",
    //   //   url: "https://rpc.enu.one",
    //   //   port: "443",
    //   //   protocol: "https",
    //   // };
    //   switch (this.env) {
    //     case 'test':
    //     case 'test2':
    //     case 'development':
    //       envobj.chainId = '6cbecff836a9fa60da53bf97a0a180103b2e76041d4414693d11bf39e2341547';
    //       break;
    //     case 'production':
    //       envobj.chainId = 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f';
    //       break;
    //     default:
    //       break;
    //   }
    // }
    // if (chainName === 'fibos') {
    //   // http://api.fibos.rocks/v1/chain/get_info
    //   // envobj = { // fibos 正式链
    //   //   host: "api.fibos.rocks",
    //   //   url: "http://api.fibos.me",
    //   //   port: "443",
    //   //   protocol: "http",
    //   // };
    //   switch (this.env) {
    //     case 'test':
    //     case 'test2':
    //     case 'development':
    //       envobj.chainId = '6aa7bd33b6b45192465afa3553dedb531acaaff8928cf64b70bd4c5e49b7ec6a';
    //       break;
    //     case 'production':
    //       envobj.chainId = '6aa7bd33b6b45192465afa3553dedb531acaaff8928cf64b70bd4c5e49b7ec6a';
    //       break;
    //     default:
    //       break;
    //   }
    // }
    // if (chainName === 'telos') {
    //   switch (this.env) {
    //     case 'test':
    //     case 'test2':
    //     case 'development':
    //       // envobj.chainId = 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f';
    //       envobj.chainId = 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f';
    //       break;
    //     case 'production':
    //       envobj.chainId = '4667b205c6838ef70ff7988f6e8257e8be0e1284a2f59699054a018f743b1d11';
    //       break;
    //     default:
    //       break;
    //   }
    // }
    // if (chainName === 'wax') {
    //   // https://chain.wax.io/v1/chain/get_info
    //   // envobj = { // wax 正式链
    //   //   host: "chain.wax.io",
    //   //   url: "https://chain.wax.io",
    //   //   port: "443",
    //   //   protocol: "https",
    //   // }
    //   switch (this.env) {
    //     case 'test':
    //     case 'test2':
    //     case 'development':
    //       // envobj.chainId = '1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4'; // 正式
    //       envobj.chainId = '4ee9d2c07bd3c4dff0bff74ab9b18711f75a03cc45e86bd98017737a95226a91';
    //       break;
    //     case 'production':
    //       envobj.chainId = '1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4';
    //       break;
    //     default:
    //       break;
    //   }
    // }
    // if (chainName === 'lynx') {
    //   // https://lynx.cryptolions.io/v1/chain/get_info
    //   // envobj = { // lynx 正式链
    //   //   host: "lynx.cryptolions.io",
    //   //   url: "https://lynx.cryptolions.io",
    //   //   port: "443",
    //   //   protocol: "https",
    //   // }
    //   switch (this.env) {
    //     case 'test':
    //     case 'test2':
    //     case 'development':
    //       // envobj.chainId = 'b62febe5aadff3d5399090b9565cb420387d3c66f2ccd7c7ac1f532c4f50f573'; // 正式
    //       envobj.chainId = '8be32650b763690b95b7d7e32d7637757a0a7392ad04f1c393872e525a2ce82b';
    //       break;
    //     case 'production':
    //       envobj.chainId = 'b62febe5aadff3d5399090b9565cb420387d3c66f2ccd7c7ac1f532c4f50f573';
    //       break;
    //     default:
    //       break;
    //   }
    // }
    return envobj;
  }

  /*
  * 获取钱包身份
  * get scatter identityInfo => publicKey
  */
  async getIdentity(chain, callback) {
    const self = this;
    this.chainName = chain.toLowerCase();
    await this.chainNodeInit(this.chainName);
    const requiredFields = { accounts:[this.network] };
    // console.log('登录前的this.scatter');
    if (!this.scatter) {
      this.scatterInit(this.vthis, () => {});
      return;
    }
    // 多账户开启
    const isOpenMoreAccount = true;
    if (store.state.app.scatter.scatterFrom === 'leafwallet' && isOpenMoreAccount) {
      requiredFields.newLogin = 1;
    }
    this.scatter.getIdentity(requiredFields).then((identity) => {
      // console.log('登录后的this.scatter');
      // console.log(identity);
      // 登录成功
      identity.accounts[0].chain = this.chainName; // 该账号所属链
      const stringIdentity = JSON.stringify(identity);
      let identityAll = JSON.parse(stringIdentity);
      const scat = store.state.app.scatter;
      scat.by = ''; // 移除扫码登录表识
      if (scat && scat.identity && scat.identity.accounts.length > 0 
      && scat.scatterFrom === 'leafwallet') {
        // 删除与当前账户相同的旧账户，并移除监听
        const userIndex = scat.identity.accounts.findIndex(v => v.name === identity.accounts[0].name &&
          v.chain === identity.accounts[0].chain );
        if (userIndex !== -1) {
          Io.accountOut(identity.accounts[0].name);
          scat.identity.accounts.splice(userIndex, 1);
        }
        identityAll = scat.identity;
        identityAll.accounts.unshift(identity.accounts[0]);
        // 移除非当前账户的监听
        identityAll.accounts.forEach((v) => {
          if (v !== identity.accounts[0].name) {
            Io.accountOut(v.name);
          }
        })
        // 排序处理
        const chains = identityAll.accounts.map(v => v.chain);
        // 去重
        const qchains = chains.filter(function(item, index, arr) {
          return arr.indexOf(item, 0) === index;
        });
        const users = [];
        qchains.forEach((v) => {
          users.push(...identityAll.accounts.filter(vv => vv.chain === v));
        });
        identityAll.accounts = users;
      } else {
        identityAll.accounts = [identityAll.accounts[0]]
      }
      const item = {
        identity: identityAll,
        wallet: 'Scatter',
        chain: this.chainName,
      }
      // console.log(this.chainName);
      if (this.chainName === 'enu' || this.chainName === 'fibos') {
        scatappOnline = true;
        item.online = true;
        item.wallet = 'Ironman';
        if (this.chainName === 'enu') {
          this.scatterEosJs = this.scatter.enu(this.network, Enu, this.eosOptions);
        }
        if (this.chainName === 'fibos') {
          this.scatterEosJs = this.scatter.enu(this.network, Fibos, this.eosOptions);
        }
      } else {
        this.scatterEosJs = this.scatter.eos(this.network, Eos, this.eosOptions);
      }
      
      this.conserveAccount(item);
      callback('success');
      // if (!this.scatter.identity) {
      //   window.location.reload();
      // }
    }).catch((error) => {
      console.log(error); // eslint-disable-line
      const scat = store.state.app.scatter;
      this.chainName = scat.chain.toLowerCase();
      this.chainNodeInit(this.chainName);
      if (self.vthis.loading) self.vthis.loading = false;
      callback(error);
      // 未解锁
      if (error.code === 423) {
        self.vthis.$confirm(self.vthis.$t('public.scatterlouck'), self.vthis.$t('public.reTip'), {
          confirmButtonText: self.vthis.$t('public.louckOk'),
          cancelButtonText: self.vthis.$t('public.louckCancel'),
          type: 'warning',
        }).then(() => {
          self.getIdentity(this.chainName, callback);
        }).catch(() => {
          callback('cancel');
        });
        return false;
      }
      this.errorCall(error, (res) => {
        self.vthis.$message.error(`${res.message} ${res.code}`);
      });
      return '';
    })
  }

  conserveAccount(item) {
    const scatterItem = store.state.app.scatter;
    this.accountByScatter = item.identity.accounts[0];
    const { identity = null, wallet, chain, online = true } = item;
    scatterItem.identity = identity;
    scatterItem.wallet = wallet;
    scatterItem.chain = chain;
    scatterItem.online = online;
    store.dispatch('setScatter', scatterItem);
    Io.accountBind(this.accountByScatter.name);
    localStorage.setItem('Frontend-Token', '');
  }

  // 退出账户
  accountLoginOut(callback) {
    let scat = store.state.app.scatter;
    if (this.scatter && this.scatter.identity) {
      // console.log('退出 -- forgetIdentity');
      this.scatter.forgetIdentity().then(() => callback());
      this.storeAccountOut(scat);
      return;
    }
    this.storeAccountOut(scat);
    callback();
  }

  storeAccountOut(scat) {
    // console.log('退出 -- storeAccountOut');
    if (scat && scat.identity) {
      Io.accountOut(scat.identity.accounts[0].name);
      scat.wallet = '';
      scat.identity = null;
      scat.chain = 'eos';
      scat.online = false;
      scat.by = '';
      localStorage.setItem('Frontend-Token', '');
      this.accountByScatter = null;
      store.dispatch('setScatter', scat);
    }
  }

  // 多账户账户退出处理
  moreAccountOut(user, callback) {
    const scat = store.state.app.scatter;
    if (scat && scat.identity) {
      const userIndex = scat.identity.accounts.findIndex(v => v.name === user.name
        && v.chain === user.chain);
      if (userIndex !== -1) {
        // 只有一个账户的退出
        if (scat.identity.accounts.length === 1) {
          this.storeAccountOut(scat);
          callback();
          window.location.reload();
          return;
        }
        Io.accountOut(user.name);
        scat.identity.accounts.splice(userIndex, 1);
        // 如果是退出了当前账户
        if (userIndex === 0) {
          this.accountByScatter = scat.identity.accounts[0];
          Io.accountBind(scat.identity.accounts[0].name);
          localStorage.setItem('Frontend-Token', '');
          scat.chain = scat.identity.accounts[0].chain;
        }
        store.dispatch('setScatter', scat).then(() => callback());
      }
    }
  }
  // 多账户更新处理
  moreAccountChange(user, callback) {
    const scat = store.state.app.scatter;
    if (scat && scat.identity) {
      const userIndex = scat.identity.accounts.findIndex(v => v.name === user.name &&
        v.chain === user.chain);
      if (userIndex !== -1) {
        // 旧账户处理
        Io.accountOut(scat.identity.accounts[0].name);
        // 新账户注入
        scat.identity.accounts[userIndex] = scat.identity.accounts.splice(0, 1, scat.identity.accounts[userIndex])[0];
        scat.chain = user.chain;

        // 排序处理
        const chains = scat.identity.accounts.map(v => v.chain);
        // 去重
        const qchains = chains.filter(function(item, index, arr) {
          return arr.indexOf(item, 0) === index;
        });
        const users = [];
        qchains.forEach((v) => {
          users.push(...scat.identity.accounts.filter(vv => vv.chain === v));
        });
        scat.identity.accounts = users;
        this.chainName = user.chain.toLowerCase();
        localStorage.setItem('Frontend-Token', user.frontendToken || '');
        this.chainNodeInit(this.chainName);
        store.dispatch('setScatter', scat).then(() => callback());
      }
    }
  }


  /*
  * 转账/交易 操作
  * @params code 智能合约
  * @params toAccount 收款者
  * @params quantity  转账额度 如：'7.0000 SYS'
  * @memo 转账备注
  */
  async eosTransaction(obj, callback) {
    const formName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const quantity = obj.quantity;
    if (this.chainName.toLowerCase() === 'fibos') {
      this.scatterEosJs.contract('eosio.token').then(ctx => {
        ctx.extransfer(formName, obj.toAccount, `${quantity}@${obj.code}`, obj.remarks, {
          authorization: formName + '@' + permission
        }).then(callback).catch((e) => {
          // this.errorCall(e, callback);
        });
      });
      return;
    }
    const params = {
      actions: [
        {
          account: obj.code,
          name: 'transfer',
          authorization: [{
            actor: formName, // 转账者
            permission,
          }],
          data: {
            from: formName,
            to: obj.toAccount,
            quantity,
            memo: obj.remarks
          }
        }
      ]
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    if (this.scatapp.wallet === 'cloudWallet') { // 云钱包下单
      WaxModel.transaction(params, (res) => {
        // console.log('cloudWallet callback');
        // console.log(res);
        if (res.processed || res.transaction_id) {
          callback(res);
          return;
        }
        this.errorCall(res, callback);
      })
      return;
    }
    // 免费CPU
    if (obj.remainFreeOrderCount > 0
      && this.chainName === 'eos') {
      this.freeCpuTransaction(params, callback);
      return;
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  async eosTransactionByEmbed(obj, callback) {
    const params = obj.data;
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    if (obj.useFreeCpu && this.chainName === 'eos') {
      this.freeCpuTransaction(params, callback);
      return;
    }
    if (this.chainName === 'eos' && obj.useFreeCpu === undefined) {
      this.freeCpuTransaction(params, callback);
      return;
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 圣诞活动转账
  */
  async transactionChristmas(obj, callback) {
    const formName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const quantity = obj.quantity;
    const params = {
      actions: [
        {
          account: 'eosio.token',
          name: 'transfer',
          authorization: [{
            actor: formName, // 转账者
            permission,
          }],
          data: {
            from: formName,
            to: 'wishcarnival',
            quantity,
            memo: obj.remarks
          }
        }
      ]
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 签名 - 合约签名
  * @params publicKey EOS账户的公钥
  * @params data EOS账户名+时间戳
  * @params whatFor 标题
  * @params isHash data是否为hash
  */
  async arbitrarySignature(vthis, timestamp, callback) {
    this.vthis = vthis;
    const data = (Math.floor(timestamp / 1000)).toString();
    const formName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const chainId = this.returnChainInfo(this.chainName).chainId;
    const back = {
      account: formName,
      timestamp: data,
      type: 'web'
    }
    
    const params = {
      actions: [
        {
          account: this.chainName === 'meetone' ? 'newdexsign.m' : 'newdexverify',
          name: 'verify',
          authorization: [{
            actor: formName,
            permission,
          }],
          data: {
            data: data.toString()
          }
        }
      ]
    }
    if (this.scatapp.wallet === 'cloudWallet') { // 云钱包签名
      WaxModel.transaction(params, (res) => {
        // console.log(res);
        if (res.signatures) {
          const chainIdBuf = new Buffer(chainId, 'hex');
          const buf = Buffer.from(Uint8Array.from(res.serializedTransaction), 'hex');
          const packedContextFreeData = new Buffer(new Uint8Array(32));
          const signBuf = Buffer.concat([chainIdBuf, buf, packedContextFreeData]);
          back.signature = res.signatures[0];
          // const verified = Ecc.verify(back.signature, signBuf, 'EOS5WcgVzNTHheFj3NEpqdfkMxY9BYNNXGAkZJU6q9yYKfBuDekvw');
          // const verified2 = Ecc.verify(res.signatures[1], signBuf, 'EOS7ZcLAK19NfV5Bbzjad9gRPFdNbHRJjCYzVf1tpw5eVF6h3NwAn');
          // const verified3 = Ecc.verify(res.signatures[1], signBuf, 'EOS5WcgVzNTHheFj3NEpqdfkMxY9BYNNXGAkZJU6q9yYKfBuDekvw');
          // const verified4 = Ecc.verify(back.signature, signBuf, 'EOS7ZcLAK19NfV5Bbzjad9gRPFdNbHRJjCYzVf1tpw5eVF6h3NwAn');
          back.signBase64 = Buffer.from(signBuf).toString('base64');
          // console.log(verified, verified2, verified3, verified4);
          callback(back);
          return;
        }
      })
      return;
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params, {
      broadcast: !1, // 是否广播
      sign: !0,
    }).then(async (res) => {
      if (res.processed || res.transaction_id) {
        const Transaction = this.scatterEosJs.fc.structs.transaction; 
        const txObject = Transaction.fromObject(res.transaction.transaction);
        const buf = Fcbuffer.toBuffer(Transaction, txObject);
        const chainIdBuf = Buffer.from(chainId, 'hex');
        const packedContextFreeData = Buffer.from(new Uint8Array(32));
        const signBuf = Buffer.concat([chainIdBuf, buf, packedContextFreeData]);
        const signature = res.transaction.signatures[0];
        // const verified = Ecc.verify(signature, signBuf, 'EOS6VPY5WayTY1gBsGz1yStG9UL991iwz9tTZoTqfKNDm5jZUqc8N');
        back.signature = signature;
        back.signBase64 = Buffer.from(signBuf).toString('base64');
        // console.log(back);
        callback(back);
        return;
      }
      this.handleScatterErrorBack(res);
    }).catch((e) => {
      this.errorCall(e, callback);
    });
    // 旧版钱包签名
    // const self = this;
    // const params = {
    //   account_name: this.accountReset()
    // };
    // self.getAccount(params, (res) => {
    //   const account = self.accountByScatter.name;
    //   const data = (Math.floor(timestamp / 1000)).toString();
    //   const authority = self.accountByScatter.authority;
    //   if (res.permissions) {
    //     const back = {
    //       account,
    //       timestamp: data,
    //       data,
    //       type: 'web'
    //     }
    //     const publicKey = res.permissions.find(v => v.perm_name === authority).required_auth.keys[0].key;
    //     console.log(this.scatapp.wallet);
    //     self.scatter.getArbitrarySignature(publicKey, data).then((signature) => {
    //       back.signature = signature;
    //       callback(back);
    //     }).catch((error) => {
    //       if (self.vthis) {
    //         self.vthis.$message.error(error);
    //       }
    //       callback(error);
    //     });
    //   }
    // });
  }

  /*
  * 买入RAM 操作
  * @params quant 额度
  */
 async eosBuyram(quant, callback) {
    const formName = this.accountReset();
    const permission = this.scatter.identity.accounts[0].authority;
    const params = {
      actions: [{ // 买入RAM
        account: 'eosio',
        name: 'buyram',
        authorization: [{
          actor: formName,
          permission,
        }],
        data: {
          payer: formName,
          receiver: formName,
          quant,
        },
      }]
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 卖出RAM 操作
  * @params quant 额度
  */
 async eosSellram(bytes, callback) {
    const formName = this.accountReset();
    const permission = this.scatter.identity.accounts[0].authority;
    const params = {
      actions: [{ // 卖出RAM
        account: 'eosio',
        name: 'sellram',
        authorization: [{
          actor: formName,
          permission,
        }],
        data: {
          account: formName,
          bytes,
        },
      }]
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 抵押CPU/NET 操作
  * @params cpu_quantity 额度
  * @params net_quantity 额度
  * @transfer: 0, // 1 给别人抵押（收不会） 0是替别人抵押（可收回）
  */
  async eosDelegatebw(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const params = {
      actions: [{
        account: 'eosio',
        name: 'delegatebw',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          from: userName,
          receiver: obj.receiver || userName,
          stake_net_quantity: obj.net_quantity,
          stake_cpu_quantity: obj.cpu_quantity,
          transfer: obj.transfer
        }
      }]
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 释放/赎回CPU/NET 操作
  * @params cpu_quantity 额度
  * @params net_quantity 额度
  */
  async eosUndelegatebw(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const params = {
      actions: [{
        account: 'eosio',
        name: 'undelegatebw',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          from: userName,
          receiver: obj.receiver || userName,
          unstake_net_quantity: obj.net_quantity,
          unstake_cpu_quantity: obj.cpu_quantity,
          transfer: obj.transfer
        }
      }]
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 抵押CPU/NET 并 投票
  * rex trasaction
  */
  async CpuNetTransaction(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const actions = [];
    if (obj.type === 0) { // cpu/net抵押
      actions.push({
        account: 'eosio',
        name: 'delegatebw',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          from: userName,
          receiver: obj.receiver,
          stake_net_quantity: obj.net_quantity,
          stake_cpu_quantity: obj.cpu_quantity,
          transfer: obj.transfer
        }
      })
    }
    if (obj.type === 1) { // cpu/net赎回
      actions.push({
        account: 'eosio',
        name: 'undelegatebw',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          from: userName,
          receiver: obj.receiver,
          unstake_cpu_quantity: obj.cpu_quantity,
          unstake_net_quantity: obj.net_quantity,
        }
      })
    }
    if (obj.way === 'newpos') {
      actions.push({ // 投票
        account: 'eosio',
        name: 'voteproducer',
        authorization: [{ 
          actor: userName,
          permission,
        }],
        data: {
          voter: userName,
          proxy: obj.proxy, // 投票的节点名称
          producers: [],
        },
      });
    }
    const params = {
      actions,
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    // 免费CPU
    if (this.chainName === 'eos'
    && obj.type === 0) {
      this.freeCpuTransaction(params, callback);
      return;
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /* 合约撤单 操作 */
  async eosOrderCancel(obj, callback) {
    const actor = this.accountReset();
    const permission = this.accountByScatter.authority;
    const dataDefault = {
      owner: actor, // 撤单账户
    }
    let data = obj.data;
    if (obj.name === 'cancelpair') {
      data = Object.assign(dataDefault, obj.data);
    }
    const params = {
      actions: [
        {
          account: obj.account, // 合约账户
          name: obj.name, // 撤单方法名
          authorization: [{
            actor, // 撤单账户
            permission, // 权限可选（active, owen）
          }],
          data,
        }
      ]
    };

    if (this.scatapp.wallet === 'cloudWallet') { // 云钱包撤单
      WaxModel.transaction(params, (res) => {
        if (res && (res.broadcast || res.processed)) { // 成功
          callback(res);
          return;
        }
        this.errorCall(res, callback);
      })
      return;
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    // 免费CPU // && obj.name === 'cancelorder'(只允许单条)
    if (this.chainName === 'eos' && obj.freeCpuChecked) {
      this.freeCpuTransaction(params, callback);
      return;
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  // 免CPU合约执行
  freeCpuTransaction(params, callback) {
    if (params.actions.length === 0) {
      params.actions[0].authorization.unshift({ actor: this.actor, permission: 'active' });
    } else {
      params.actions.forEach((item) => {
        item.authorization.unshift({
          actor: this.actor,
          permission: 'active',
        })
      })
    }
    this.scatterEosJs.transaction(params, {
      broadcast: !1, // 是否广播
      sign: !0,
    }).then((res) => {
      if (res.processed || res.transaction_id) {
        const l = res.transaction.transaction;
        l.signatures = res.transaction.signatures;
        l.context_free_data = [];
        const signed = JSON.stringify(l);
        this.handleFreeCpuSend(signed, callback);
        return;
      }
      this.handleScatterErrorBack(res);
    }).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  // 广播免费CPU
  handleFreeCpuSend(signed, callback) {
    try {
      const host = location.origin;
      let url = `${host}/cpu/pushTxWithoutCPU`;
      if (this.env !== 'production') {
        url = `http://${getReqUrl('cpu')}:${process.env.VUE_APP_PORT2}/cpu/pushTxWithoutCPU`;
      }
      axios.post(url, { signed }, {
        headers: {
          accept: 'application/json, text/plain, */*',
        },
      }).then((res) => {
        // console.log(res);
        if (res.data.code === 200) {
          callback({processed: true, transaction_id: true});
          return;
        }
        callback(res);
      });
    } catch (err) {
      this.$message.error(JSON.stringify(err));
    }
  }

  // 会员机制切换抵押模式和消耗模式
  async newdexStakexChange(obj, callback) {
    const actor = this.accountReset();
    const permission = this.accountByScatter.authority;
    const isStaked = obj.model;
    const shuhui = [
      {
        account: 'newdexstaked',
        name: obj.name,
        authorization: [{
          actor,
          permission,
        }],
        data: {
          owner: actor,
          quantity: obj.quantity,
          blockchain: obj.chain,
          stakefor: obj.stakeAccount,
        }
      }
    ]
    const params = {
      actions: [
        {
          account: 'newdexstaked',
          name: 'choosemode',
          authorization: [{
            actor,
            permission,
          }],
          data: {
            owner: actor,
            is_staked: isStaked,
          }
        }
      ]
    }
    if (obj.checked) {
      params.actions.unshift(...shuhui);
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /** 
   * 会员消耗模式
   * @param obj.memo // memo说明：vip等级-月数（有效期）-订单拥有人
   * */
  async newdexissuerAction(obj, callback) {
    const actor = this.accountReset();
    const permission = this.accountByScatter.authority;
    const params = {
      actions: [
        {
          account: 'newdexissuer',
          name: 'transfer',
          authorization: [{
            actor,
            permission,
          }],
          data: {
            from: actor,
            to: 'newdexstaked',
            quantity: obj.quantity,
            memo: obj.memo,
          }
        }
      ]
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  // NDX抵押stake / 赎回unstake
  async newdexStakex(obj, callback) {
    const actor = this.accountReset();
    const permission = this.accountByScatter.authority;
    const params = {
      actions: [
        {
          account: 'newdexstaked',
          name: obj.name,
          authorization: [{
            actor,
            permission,
          }],
          data: {
            owner: actor,
            quantity: obj.quantity,
            blockchain: obj.chain,
            stakefor: obj.stakeAccount,
          }
        }
      ]
    }
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  // NDX抵押信息
  async newdexStakexInfo(obj, callback) {
    const userName = Eos.modules.format.encodeName(this.accountReset(), false);
    let actor = obj.actor === 'account' ? userName : obj.actor;
    const params = {
      "json": true,
      "code": "newdexstaked",
      "scope": actor,
      "table": obj.name
    };
    if (obj.name === 'stakeddetail') {
      params.table = 'stake2others';
      params.limit = 500;
    }
    if (obj.name === 'stake') {
      params.lower_bound = obj.chain;
      params.upper_bound = obj.chain;
      params.table = 'stakes';
    }
    // 配置
    if (!this.EosJsUse) {
      await this.chainNodeInit('eos')
    }
    this.EosJsUse.getTableRows(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 获取eos账号余额
  * @params code
  * @params symbol
  * @params eosAccount
  * @return Balance
  */
  async getCurrencyBalance(symbol, code, callback) {
    const params = {
      code,
      symbol,
      account: this.accountReset()
    };
    if (!this.EosJs) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJs.getCurrencyBalance(params).then((results, error) => {
      callback(results);
    }).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 获取eos账号信息
  * @params eosAccount
  * @return 账户信息
  */
  async getAccount(params, callback) {
    if (!this.EosJs) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJs.getAccount(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 获取 "account_name": "eosio.ram", 
  * ram 时时交易数据
  */
  async getRamActions(obj, callback) {
    const params = {
      "account_name": obj.account_name,
      "pos": obj.pos,
      "offset": obj.offset
    };
    if (!this.EosJs) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJs.getActions(params).then((rammarket) => callback(rammarket)).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 获取 getTableRows
  */
  async getTableRows(callback) {
    const params = {
      "json": true,
      "code": "eosio",
      "scope": "eosio",
      "table": "rammarket"
    };
    // 配置
    if (!this.EosJsUse) {
      await this.chainNodeInit('eos')
    }
    this.EosJsUse.getTableRows(params).then((rammarket) => callback(rammarket)).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 
  * 判断合约的方式
  */
  async getRawAbi(obj) {
    return new Promise((resolve, reject) => {
      const params = {
        account_name:  obj.account || this.accountReset()
      };
      let envobj = store.state.app.nodeChecked['eos'];
      let url = `${envobj.url}/v1/chain/get_raw_abi`;
      axios.post(url, params,  {
        headers: {
          'Content-Type': 'text/plain;charset=UTF-8',
        }
      }).then((res) => {
        if (res.status === 200) {
          resolve(res.data)
        }
        reject(res)
      }).catch((err) => {
        reject(err)
      });
    })
  }

  /*
  * 获取 rex 数据 TableRows
  */
  async getRexTableRows(callback) {
    // const testEosJs = Eos({
    //   httpEndpoint: 'https://mainnet.eoscanada.com',
    //   chainId: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906',
    //   verbose: false,
    // });
    const params = {
      code: "eosio",
      json: true,
      scope: "eosio",
      table: "rexpool",
    };
    // testEosJs.getTableRows(params).then((res) => {
    //   const row = res.rows[0];
    //   callback(row)
    // }).catch((e) => {
    //   this.errorCall(e, callback);
    // });
    // 配置
    if (!this.EosJsUse) {
      await this.chainNodeInit('eos')
    }
    this.EosJsUse.getTableRows(params).then((res) => {
      const row = res.rows[0];
      callback(row)
    }).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * REX 买卖
  * rex trasaction
  */
  async rexTransaction(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const voterInfo = store.state.app.accountRes;
    const producers = voterInfo.producers;
    const proxy = voterInfo.proxy;
    let amount = obj.amount;
    let actions = [];
    if (!obj.hasResources && obj.action === 'buyrex') { // 如果没有给自己抵押资源的
      const ab = amount.split(' ');
      actions.push({ // cpu/net抵押
        account: 'eosio',
        name: 'delegatebw',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          from: userName,
          receiver: userName,
          stake_net_quantity: '0.0000 ' + ab[1],
          stake_cpu_quantity: '0.0001 ' + ab[1],
          transfer: 0
        }
      })
      amount = accSub(Number(ab[0]), 0.0001);
      amount = `${toFixed(Number(amount), 4)} ${ab[1]}`;
    }
    if ((obj.action === 'buyrex' && !proxy && producers.length < 21)
    || (obj.way === 'newpos')) {
      actions.push({ // 投票
        account: 'eosio',
        name: 'voteproducer',
        authorization: [{ 
          actor: userName,
          permission,
        }],
        data: {
          voter: userName,
          proxy: obj.proxy, // 投票的节点名称
          producers: [],
        },
      });
    }
    if (obj.action === 'buyrex') {
      const buyaction = [
        { // 充值
          account: 'eosio',
          name: 'deposit',
          authorization: [{
            actor: userName,
            permission,
          }],
          data: {
            owner: userName,
            amount, // eos 数量
          },
        },
        { // 买入：buyrex
          account: 'eosio',
          name: 'buyrex',
          authorization: [{
            actor: userName,
            permission,
          }],
          data: {
            from: userName,
            amount, // eos 数量
          },
        }
      ];
      actions.push(...buyaction);
    }
    if (obj.action === 'sellrex') {
      actions.push({ // 卖出：sellrex
        account: 'eosio',
        name: 'sellrex',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          from: userName,
          rex: obj.rex
        },
      },
      { // 提现
        account: 'eosio',
        name: 'withdraw',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          owner: userName,
          amount: obj.getEos
        },
      })
    }
    const params = {
      actions,
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    if (this.scatterEosJs.fc.abiCache) {
      this.scatterEosJs.fc.abiCache.abi("eosio", abi);
      this.scatterEosJs.transaction(params).then(callback).catch((e) => {
        this.errorCall(e, callback);
      });
      return;
    }
    const err = {
      code: 'Scatter',
    }
    this.errorCall(err, callback);
  }

  /*
  * 投票
  */
  async voteproducerAction(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const params = {
      actions: [
        { // 投票
          account: 'eosio',
          name: 'voteproducer',
          authorization: [{ 
            actor: userName,
            permission,
          }],
          data: {
            voter: userName,
            proxy: obj.proxy, // 投票的节点名称
            producers: [],
          },
        }
      ]
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    if (this.scatterEosJs.fc.abiCache) {
      this.scatterEosJs.fc.abiCache.abi("eosio", abi);
      // 免费CPU 叶子钱包
      if (this.chainName === 'eos') {
        this.freeCpuTransaction(params, callback);
        return;
      }
      this.scatterEosJs.transaction(params).then(callback).catch((e) => {
        this.errorCall(e, callback);
      });
      return;
    }
    const err = {
      code: 'Scatter',
    }
    this.errorCall(err, callback);
  }

  /*
  * 赎回 并买入REX
  */
  async rexUnstaketorexTransaction(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const voterInfo = store.state.app.accountRes;
    const producers = voterInfo.producers;
    const proxy = voterInfo.proxy;
    let actions = [];
    if (!proxy && producers.length < 21) {
      actions = [{ // 投票
        account: 'eosio',
        name: 'voteproducer',
        authorization: [{ 
          actor: userName,
          permission,
        }],
        data: {
          voter: userName,
          proxy: obj.proxy, // 投票的节点名称
          producers,
        },
      }]
    }
    const buyaction = [
      {
        account: 'eosio',
        name: 'unstaketorex',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          owner: userName,
          receiver: obj.receiver || userName, // 其它用户给你的抵押
          from_net: obj.fromNet,
          from_cpu: obj.fromCpu
        },
      },
    ];
    actions.push(...buyaction);
    const params = {
      actions,
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    if (this.scatterEosJs.fc.abiCache) {
      this.scatterEosJs.fc.abiCache.abi("eosio", abi);
      this.scatterEosJs.transaction(params).then(callback).catch((e) => {
        this.errorCall(e, callback);
      });
      return;
    }
    const err = {
      code: 'Scatter',
    }
    this.errorCall(err, callback);
  }

  /*
   * REX 余额及冻结数据
  */
  async getRexBlance(callback) {
    const userName = Eos.modules.format.encodeName(this.accountReset(), false);
    const params = {
      code: "eosio",
      json: true,
      limit: 1,
      lower_bound: userName,
      scope: "eosio",
      table: "rexbal",
      table_key: "",
      upper_bound: userName,
    };
    if (!this.EosJs) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJs.getTableRows(params).then(res => callback(res)).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
   * 获取 用户储备金余额
  */
  async getRexFundBlance(callback) {
    const userName = Eos.modules.format.encodeName(this.accountReset(), false);
    const params = {
      code: "eosio",
      json: true,
      limit: 1,
      lower_bound: userName,
      scope: "eosio",
      table: "rexfund",
      table_key: "",
      upper_bound: userName,
    };
    if (!this.EosJs) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJs.getTableRows(params).then(res => callback(res)).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * cpu/net 租赁
  * cpu/net trasaction
  */
  async cpuTransaction(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const amount = obj.amount;
    const loan_fund = obj.loanFund;
    const name = obj.type ? 'rentnet' : 'rentcpu';
    let actions = [];
    if (parseFloat(amount, 0) !== 0) {
      actions.push({ // 充值
        account: 'eosio',
        name: 'deposit',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          owner: userName,
          amount, // eos 数量
        },
      })
    }
    actions.push({ // cpu/net租赁
      account: 'eosio',
      name,
      authorization: [{
        actor: userName,
        permission,
      }],
      data: {
        from: userName,
        receiver: obj.receiver,
        loan_payment: obj.loanPayment,
        loan_fund,
      },
    });
    const params = {
      actions,
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    if (!this.scatterEosJs.fc.abiCache && !parseFloat(amount, 0)) {
      const err = {
        code: 'Scatter',
      }
      this.errorCall(err, callback);
      return;
    }
    if (this.scatterEosJs.fc.abiCache) {
      this.scatterEosJs.fc.abiCache.abi("eosio", abi);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * cpu/net 存入/取回 续租租金
  * cpu/net trasaction
  * cpu 存 fundcpuloan  @from @loan_num  @payment
    cpu 取 defcpuloan   @from @loan_num @amount 
    net 存 fundnetloan  @from @loan_num  @payment
    net 取 defnetloan   @from @loan_num @amount 
  */
  async cpuOperationTransaction(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const amount = obj.amount;
    let actions = [];
    let name = '';
    if (parseFloat(amount, 0) !== 0 && obj.way === 1) {
      actions.push({ // 充值
        account: 'eosio',
        name: 'deposit',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          owner: userName,
          amount, // eos 数量
        },
      })
    }
    if (obj.way === 1) { // 存
      name = `fund${obj.type}loan`
      actions.push({ // cpu/net 存
        account: 'eosio',
        name,
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          from: userName,
          loan_num: obj.loan_num,
          payment: obj.payment,
        },
      });
    } else {  // 取
      name = `def${obj.type}loan`;
      actions.push({ // cpu/net 取
        account: 'eosio',
        name,
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          from: userName,
          loan_num: obj.loan_num,
          amount: obj.defAmount,
        },
      });
      actions.push({ // 提现
        account: 'eosio',
        name: 'withdraw',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          owner: userName,
          amount: obj.defAmount
        },
      })
    }
    const params = {
      actions,
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    if (!this.scatterEosJs.fc.abiCache && !parseFloat(amount, 0)) {
      const err = {
        code: 'Scatter',
      }
      this.errorCall(err, callback);
      return;
    }
    if (this.scatterEosJs.fc.abiCache) {
      this.scatterEosJs.fc.abiCache.abi("eosio", abi);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 取回 REX 储备金 
  */
  async withdrawTransaction(obj, callback) {
    const userName = this.accountReset();
    const permission = this.accountByScatter.authority;
    const params = {
      actions: [{ // 提现
        account: 'eosio',
        name: 'withdraw',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          owner: userName,
          amount: obj.amount
        },
      }]
    };
    if (!this.scatterEosJs) {
      await this.chainNodeInit(this.chainName);
    }
    if (!this.scatterEosJs.fc.abiCache) {
      const err = {
        code: 'Scatter',
      }
      this.errorCall(err, callback);
      return;
    }
    if (this.scatterEosJs.fc.abiCache) {
      this.scatterEosJs.fc.abiCache.abi("eosio", abi);
    }
    this.scatterEosJs.transaction(params).then(callback).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * cpu/net 当前租赁列表
  */
  async getCpuNetList(obj, callback) {
    // Eos.modules.format.encodeName(this.accountReset(), false);
    const userName = this.accountReset();
    const params = {
      code: "eosio",
      index_position: 3,
      json: true,
      key_type: "name",
      limit: 100,
      lower_bound: userName,
      scope: "eosio",
      table: obj.table, // "cpuloan"  "netloan"
      table_key: "",
      upper_bound: userName,
    };
    if (!this.EosJsUse) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJsUse.getTableRows(params).then(res => callback(res)).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 获取所有的抵押账户
  */
  async getTableRowsForStaket(callback) {
    const userName = Eos.modules.format.encodeName(this.accountReset(), false);
    const params = {
      code: "eosio",
      json: true,
      limit: 50,
      lower_bound: "",
      scope: userName,
      table: "delband",
      table_key: "",
      upper_bound: "",
    };
    if (!this.EosJsUse) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJsUse.getTableRows(params).then((rammarket) => callback(rammarket)).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 获取 getTableRows for Fibos 链
  */
  async getTableRowsForFibos(callback) {
    const userName = this.accountReset(); // Eos.modules.format.encodeName(this.accountReset(), false);
    const params = {
      "json": true,
      "code": "eosio.token",
      "scope": userName,
      "table": "accounts",
    };
    if (!this.FibosJs) {
      await this.chainNodeInit('fibos');
    }
    this.FibosJs.getTableRows(params).then((rammarket) => callback(rammarket)).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 获取订单条数
  */
  async getTableRowsForOrders(callback) {
    const userName = Eos.modules.format.encodeName(this.accountReset(), false);
    if (!userName || this.chainName !== 'eos') return;
    const params = {
      code: 'newdexpublic',
      scope: 'newdexpublic',
      table: 'account',
      lower_bound: userName,
      upper_bound: userName,
      json: true
    };
    if (!this.EosJs) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJs.getTableRows(params).then((rammarket) => callback(rammarket)).catch((e) => {
      this.errorCall(e, callback);
    });
  }

  /*
  * 获取Ram 实时价格
  */
  getRamPrice(callback) {
    this.getTableRows((rammarket) => {
      try {
        var ramcoreAmount = rammarket.rows[0].supply.split(" ")[0] * 10000;
        var ramBaseBalance = rammarket.rows[0].base.balance.split(" ")[0];
        var ramQuoteBalance = rammarket.rows[0].quote.balance.split(" ")[0] * 10000;
        var ramBaseWeight = rammarket.rows[0].base.weight;
        var ramQuoteWeight = rammarket.rows[0].quote.weight;

        var iEos = 9950.0;
        var R, C, F, T, ONE, E, issued, out, buyRamBytes, ramPrice, iBytes, sellEos;
        R = ramcoreAmount;
        C = ramQuoteBalance + iEos;
        F = ramQuoteWeight / 1000.0;
        T = iEos;
        ONE = 1.0;
        E = ( -1 * R) * (ONE - Math.pow((ONE + T / C), F));
        issued = parseInt(E);

        R = ramcoreAmount;
        C = ramBaseBalance;
        F = 1000.0 / ramBaseWeight;
        E = issued;
        T = C * (Math.pow((ONE + E / R), F) - ONE);
        out = parseInt(T);
        buyRamBytes = out;
        ramPrice = out / (iEos / 10000.0);
        ramPrice = 1024.0 / (parseFloat(ramPrice));
        iBytes = 1024;

        R = ramcoreAmount;
        C = ramBaseBalance - buyRamBytes + iBytes;
        F = ramBaseWeight / 1000.0;
        T = iBytes;
        E = ( -1 * R) * (ONE - Math.pow((ONE + T / C), F));
        sellEos = parseInt(E);
        C = ramQuoteBalance + iEos;
        F = 1000.0 / ramQuoteWeight;
        E = sellEos;
        T = C * (Math.pow((ONE + E / R), F) - ONE);
        out = parseInt(T);
        C = ramQuoteBalance + iEos;
        iEos = 10000.0 * 0.995;
        C = C + iEos;
        F = ramQuoteWeight / 1000.0;
        T = iEos;
        E = ( -1 * R) * (ONE - Math.pow((ONE + T / C), F));
        issued = parseInt(E);
        C = ramBaseBalance - buyRamBytes;
        F = 1000.0 / ramBaseWeight;
        E = issued;
        T = C * (Math.pow((ONE + E / R), F) - ONE);
        out = parseInt(T);
        ramPrice = out / (iEos / 10000.0);
        ramPrice = 1024.0 / (parseFloat(ramPrice));
        callback(ramPrice, rammarket);
      } catch (error) {
      }
    })
  }

  /*
  * 获取eos账号
  * @params privatekey 私钥
  * @get publickey 公钥
  * @return eosAccounts
  */
  async getKeyAccounts(privateKey, callback) {
    const publicKey = Ecc.privateToPublic(privateKey);
    const params = {
      public_key: publicKey,
    };
    if (!this.EosJs) {
      await this.chainNodeInit(this.chainName)
    }
    this.EosJs.getKeyAccounts(params, callback)
  }

  accountReset() {
    const item = {
      name: '',
      authority: '',
    }
    const identity = store.state.app.scatter.identity;
    if (!identity) return item.name;
    this.accountByScatter = identity.accounts[0];
    return this.accountByScatter.name;
  }

  // REX 数据实时更新
  updaterexTransaction() {
    const userName = this.accountReset() || '';
    if (!userName) return;
    const permission = this.accountByScatter.authority;
    const params = {
      actions: [{
        account: 'eosio',
        name: 'updaterex',
        authorization: [{
          actor: userName,
          permission,
        }],
        data: {
          owner: userName,
        },
      }]
    };
    if (this.scatterEosJs.fc.abiCache) {
      this.scatterEosJs.fc.abiCache.abi("eosio", abi);
    }
    this.scatterEosJs.transaction(params).then(() => {});
  }

  // scatter操作回调
  handleScatterErrorBack(res) {
    console.log('Error');
    console.log(res);
    if (res.code || res.error) {
      let code = res.code;
      if (code === 500 && res.error) {
        code = res.error.code;
      }
      if (res.error && res.error.details && res.error.details.length > 0
        && code !== 3080001
        && code !== 3080002
        && code !== 3080004
        && code !== 3040005) {
        const errorDetails = res.error.details[0].message.split(':')[1] || res.error.details[0].message;
        if (errorDetails && errorDetails.indexOf('your orders has exceeded') >= 0) {
          const arr = errorDetails.trim().split(' ');
          const amount = arr[arr.length - 2];
          this.vthis.$message.error(`${this.vthis.$t('tronExchange.entrustmentTip3', {amount})}`);
          return;
        }
        this.vthis.$message.error(`${errorDetails}【${code}】`);
        return;
      }
      switch (code) {
        case 3080001:
          this.vthis.$message.error(`${this.vthis.$t('error.error3080001')}【${code}】`);
          break;
        case 3080002:
          this.vthis.$message.error(`${this.vthis.$t('error.error3080002')}【${code}】`);
          break;
        case 3080004:
          this.vthis.$message.error(`${this.vthis.$t('error.error3080004')}【${code}】`);
          break;
        case 3040005:
          this.vthis.$message.error(`${this.vthis.$t('error.error3040005')}【${code}】`);
          break;
        case 3050003:
          this.vthis.$message.error(`${this.vthis.$t('error.error3050003')}【${code}】`);
          break;
        default:
          if (res.code && res.message) {
            this.vthis.$message.error(`${res.message} 【${res.code}】`);
            return;
          }
          this.vthis.$message.error(`${res.message} 【${code}】`);
          break;
      }
      return;
    }
    if (res.data && res.data.code === 500 && typeof(res.data.message) === 'string') {
      const fjres = eval('('+res.data.message+')');
      this.handleScatterErrorBack(fjres);
      return;
    }
    this.vthis.$message.error(`Unknow Error!【${res}】`);
  }

  //  catch 错误回调
  errorCall(e, callback) {
    const self = this;
    const scatapp = store.state.app.scatter;
    console.log('error callback', typeof(e), e); // eslint-disable-line
    let back = {
      code: 100001,
      error: {
        code: 100001
      },
      message: 'Unknown anomaly',
    };
    if (typeof (e) === 'object') {
      back = {
        code: '402',
        error: {
          code: '402',
        },
        message: e.message || 'Privileges have been lost. Please log in again.',
      }
      if (e.code === 402) {
        back.message = e.message;
      }
      if (e.code === 'Scatter') {
        // ${this.vthis.$t('error.error3040005')}
        back.code = '100002'
        back.message = this.vthis.$t('public.scatterDesktop');
      }
      if (e.Error && typeof (e.Error) === 'string' && e.Error.indexOf('No Identity') >= 0) {
        back.message = 'Privileges have been lost. Please log in again.';
        self.accountLoginOut(() => {
          self.getIdentity(self.chainName, () => {});
        });
      }
      if (scatapp && scatapp.identity && !scatterConnected) {
        self.initNext();
      }
      if (e.name === "AssertionError") {
        back.code = '500';
        back.message = e.message;
      }
    }
    if (typeof (e) === 'string') {
      if (e.indexOf('code') >= 0) {
        back = JSON.parse(e);
      } else if(e.indexOf('Failed to fetch') >= 0) {
        back = {
          code: '0001',
          error: {
            code: '0001',
          },
          message: this.vthis.$t('public.anotherNode')
        }
      } else {
        back = {
          code: '0002',
          error: {
            code: '0002',
          },
          message: 'Failed to get the balance',
        }
      }
    }
    callback(back);
  }
}

export const ChainModel = new model();
export const model2 = model;
export const EosModel = new model();
